package repeater

import (
    "../common"
    //"fmt"
    //"math/rand"
    //"time"
    logging "github.com/op/go-logging"
    "time"
)


var log = logging.MustGetLogger("repeater")

func SetLogger(l *logging.Logger) {
    log = l
}

type Sender interface {
    Output() <-chan *DataPointPack
    //SetOffset(int64)
}

type Repeater interface {
    Init() error
    Start()
    Stop() error
    Name() string
    Handle(*DataPointPack) error
    SetController(*RepeaterController) error
    Commit() (int64, error)
}

type DataPointPack struct {
    Datapoints []*common.DataPoint
    Offsets    []int64
    count      int
    ctime      int64
    msgTime    uint32
    from       uint32
    to         uint32
}

func NewDataPointPack() *DataPointPack {
    return &DataPointPack{
        Datapoints: make([]*common.DataPoint, 0),
        Offsets:    make([]int64, 0),
        count:      0,
        ctime:      time.Now().Unix(),
        msgTime:    0,
    }
}

func (dpp *DataPointPack)Reset(){
    dpp.Offsets = nil
    for _,dp:=range dpp.Datapoints {
        common.ReleaseDatapoint(dp)
    }
    dpp.count=0
    dpp.ctime=0
    dpp.msgTime=0
    dpp.from=0
    dpp.to=0
}

func (dpp *DataPointPack) AddDataPoint(dp *common.DataPoint, o int64) {
    dpp.Offsets = append(dpp.Offsets, o)
    dpp.Datapoints = append(dpp.Datapoints, dp)
    dpp.count += 1
    dpp.msgTime = dp.Time
    if dpp.from==0||dpp.from>dp.Time{
        dpp.from=dp.Time
    }
    if dpp.to==0||dpp.to<dp.Time{
        dpp.to=dp.Time
    }
}
func (dpp *DataPointPack) IsReday(size int, ttl int64) bool {
    return size < dpp.count || ttl < time.Now().Unix()-dpp.ctime
}
func (dpp *DataPointPack) Offset() (o int64) {
    o = DEFAULT_OFFSET
    if len(dpp.Offsets) < 1 {
        return
    }
    o = dpp.Offsets[0]
    for i := 1; i < len(dpp.Offsets); i++ {
        if o+1 == dpp.Offsets[i] {
            o = dpp.Offsets[i]
        } else {
            log.Noticef("data pack offset inconsist")
            break
        }
    }
    return
}

//
//type ConsoleReceiver struct {
//	rc      *RepeaterController
//	name    string
//	passOut bool
//}
//
//func (cs *ConsoleReceiver) Init() error {
//	return nil
//}
//func (cs *ConsoleReceiver) Start() {
//	cs.rc.waitGroup().Add(1)
//}
//func (cs *ConsoleReceiver) Stop() error {
//	cs.rc.waitGroup().Done()
//	fmt.Println("console receiver stop")
//	return nil
//}
//func (cs *ConsoleReceiver) Name() string {
//	return "console receiver"
//}
//func (cs *ConsoleReceiver) CheckAlive() bool {
//	return true
//}
//
////return nil if not sender
//func (cs *ConsoleReceiver) Handle(dp *common.DataPointWithOffset) (*common.DataPointWithOffset, error) {
//	fmt.Printf("%s : %v\n", cs.name, dp)
//	if cs.passOut {
//		return dp, nil
//	}
//	return nil, nil
//}
//func (cs *ConsoleReceiver) SetController(rc *RepeaterController) error {
//	cs.rc = rc
//	return nil
//}
//func (cs *ConsoleReceiver) Commit() (int64, error) {
//	return 0, nil
//}
//
//type RandomSender struct {
//	output chan *common.DataPointWithOffset
//	times  int
//	rr     *rand.Rand
//	rc     *RepeaterController
//}
//
//func (rs *RandomSender) Init() error {
//	rs.rr = rand.New(rand.NewSource(17))
//	rs.output = make(chan *common.DataPointWithOffset)
//	rs.times = 10
//	return nil
//}
//func (rs *RandomSender) Start() {
//	rs.rc.waitGroup().Add(1)
//	defer rs.rc.waitGroup().Done()
//	for count := 0; count < rs.times; count++ {
//		rs.output <- &common.DataPointWithOffset{"golia.121_33_12_91.nn.nnn", rs.rr.Float64(), uint32(time.Now().Unix()), int64(count)}
//	}
//	close(rs.output)
//}
//func (rs *RandomSender) Stop() error {
//	return nil
//}
//func (rs *RandomSender) Name() string {
//	return "radom sender"
//}
//func (rs *RandomSender) CheckAlive() bool {
//	return true
//}
//func (rs *RandomSender) output() <-chan *common.DataPointWithOffset {
//	return rs.output
//} //return nil if not sender
//func (rs *RandomSender) Handle(dp *common.DataPointWithOffset) (*common.DataPointWithOffset, error) {
//	return dp, nil
//}
//func (rs *RandomSender) SetController(rc *RepeaterController) error {
//	rs.rc = rc
//	return nil
//}
//func (rs *RandomSender) Commit() (int64, error) {
//	return 0, nil
//}
